// tsc -t es5 4-1.ts && node 4-1.js
// ts-node 4-1.ts 

// 4-1 对象object
const person = {
    firstName: 'madison',
    lastName: 'zhuang',
    age: 18
}

// person.age = '23'
// console.log(person.nickname)

const person1: { firstName: string, lastName: string, age: number } = {
    firstName: 'madison',
    lastName: 'zhuang',
    age: 18
}

const person2: object = {
    firstName: 'madison',
    lastName: 'zhuang',
    age: 18
}
// console.log(person2.firstName)

const person3: any = {
    firstName: 'madison',
    lastName: 'zhuang',
    age: 18
}
console.log(person3.nickname)


// 4-2 Interface 与class
let drasPoint = (x:number, y:number) => {
    console.log(x, y)
}

let drasPoint1 = (point:Point) => {
    console.log(point.x, point.y)
}
drasPoint1({ x: 10, y: 20 })
// drasPoint1({ x: 'madsi', y: 'ss' })
// drasPoint1({ wether: '干燥', temperatur: '5oc' })

interface Point {
    x: number,
    y: number
}
let drasPoint2 = (point: Point) => {
    console.log(point.x, point.y)
}
drasPoint2({ x: 10, y: 20 })
// drasPoint2({ x: 'madsi', y: 'ss' })
// drasPoint2({ wether: '干燥', temperatur: '5oc' })

let getDistances = (a: Point, b: Point) => {
    // ...
}

// interface IPoint {
//     // x: number
//     // y: number
//     drawPoint: () => void
//     getDistances: (p: IPoint) => number

//     X: number
//     // getX: () => number
//     getY: () => number
//     // setX: (value) => void
//     setY: (value) => void
// }

// class PointImpl implements IPoint {
//     // x: number
//     // y: number

//     // constructor(x?: number, y: number=3) {
//     //     this.x = x
//     //     this.y = y
//     // }

//     // constructor(public x: number, public y: number = 3) { }

//     constructor(private _x: number, private _y: number = 3) { }

//     drawPoint = () => {
//         console.log('x:', this._x, ' y:', this._y);

//     }
//     getDistances = (p: IPoint) => {
//         return Math.pow(p.X - this._x, 2) + Math.pow(p.getY() - this._y, 2)
//     }

//     // setX = (value: number) => {
//     //     if (value < 0) {
//     //         throw new Error('value不能小于0')
//     //     }
//     //     this.x = value
//     // }

//     // getX = () => {
//     //     return this.x
//     // }

//     setY = (value: number) => {
//         if (value < 0) {
//             throw new Error('value不能小于0')
//         }
//         this._y = value
//     }

//     getY = () => {
//         return this._y
//     }

//     set X(value: number) {
//         if (value < 0) {
//             throw new Error('value不能小于0')
//         }
//         this._x = value
//     }

//     get X() {
//         return this._x
//     }
// }

import { PointImpl } from "./point"
const point = new PointImpl(2, 3) // 对象object, 实例instance
// point.x = 2
// point.y = 3
point.drawPoint()
// 对象object、类clas、实例instance

// Access Modifier 访问修饰符
// public private protected
const point1 = new PointImpl(24, 50)
// point1.x = 30
// point1.y = 5
// point1.setX(20)
console.log(point1.X)
// tsc -t es5 4-1.ts



// Generics 泛型

// let list1: number[] = [1, 2, 3]
// let list2: Array<string> = [1, 2, 3, 4]
let lastInArray = <T>(arr: T[]) => {
    return arr[arr.length - 1]
}
const l1 = lastInArray<number>([1, 2, 3, 4])
console.log(l1)
const l2 = lastInArray<string>(['a', 'b', 'c'])
console.log(l2)
const l3 = lastInArray<string | number>(['a', 'b', 'c', 1])
console.log(l3)

let makeTuple = <T, Y = number>(x: T, y: Y) => [x, y]
const v1 = makeTuple(1, '1')
console.log(v1)
const v2 = makeTuple<boolean, number>(true, 1)
console.log(v2)